import axios from "axios";
import jsonp from "jsonp";
// axios.defaults.withCredentials = true;
import { Toast } from 'antd-mobile'
import { useNavigate } from 'react-router-dom';
const $globalRequestUrl = (params) => {
  const { VITE_BASE_URL } = import.meta.env;
  const baseUrl = VITE_BASE_URL;
  return `${params.baseUrl ? params.baseUrl : baseUrl}${params.url}`;
};
const $globalUploaderRequest = (params) => {
  const { VITE_UPLOADER_BASE_URL } = import.meta.env;
  const baseUrl = VITE_UPLOADER_BASE_URL;
  return `${params.baseUrl ? params.baseUrl : baseUrl}${params.url}`;
};

function extend(dst) {
  for (let i = 1, ii = arguments.length; i < ii; i++) {
    let obj = arguments[i];
    if (obj) {
      let keys = Object.keys(obj);
      for (let j = 0, jj = keys.length; j < jj; j++) {
        let key = keys[j];
        dst[key] = obj[key];
      }
    }
  }
  return dst;
}

/**
 * @description:jsonp url拼接参数
 * @param {Object} data
 * @returns {String}
 */
const paramJsonp = (data) => {
  let url = "";

  for (var k in data) {
    if (Object.property.hasOwnProperty.call(data, k)) {
      let value = data[k] !== undefined ? data[k] : "";

      url += "&" + k + "=" + encodeURIComponent(value);
    }
  }
  return url ? url.substring(1) : "";
};

/**
 * @description:jsonp
 * @param {String} url
 * @param {Object} data
 * @param {Object} option
 */
const getJsonpData = (url, data, option) => {
  url += (url.indexOf("?") < 0 ? "?" : "&") + paramJsonp(data);
  return new Promise((resolve, reject) => {
    jsonp(url, option, (err, data) => {
      if (!err) {
        resolve(data);
      } else {
        reject(err);
      }
    });
  });
};

/**
 * @description:post
 * @param {Object} config
 */
const post = (config) => {
  return new Promise((resolve, reject) => {
    extend(config, {
      method: "post",
    });
    axios(config).then(
      (rep) => {
        resolve(rep);
      },
      (error) => {
        reject(error);
      }
    );
  });
};

/**
 * @description:PUT
 * @param {Object} config
 */
const put = (config) => {
  return new Promise((resolve, reject) => {
    extend(config, {
      method: "PUT",
    });
    axios(config).then(
      (rep) => {
        resolve(rep);
      },
      (error) => {
        reject(error);
      }
    );
  });
};

/**
 * @description:get
 * @param {Object} config
 */
const get = (config) => {
  return new Promise((resolve, reject) => {
    extend(config, {
      method: "GET",
    });
    axios(config)
      .then((rep) => {
        resolve(rep);
      })
      .catch((error) => {
        reject(error);
      });
  });
};

/**
 * @description:delete
 * @param {Object} config
 */
const Delete = (config) => {
  return new Promise((resolve, reject) => {
    extend(config, {
      method: "DELETE",
    });
    axios(config).then(
      (rep) => {
        resolve(rep);
      },
      (error) => {
        reject(error);
      }
    );
  });
};

/**
 * @description: handlePostFormdata
 * @param {Object} params
 */
const handlePostFormdata = (params) => {
  let fd = new FormData();
  for (let i in params) {
    if (params[i] instanceof Array) {
      for (let j = 0; j < params[i].length; j++) {
        for (let k in params[i][j]) {
          if (Object.property.hasOwnProperty.call(params[i][j], k)) {
            let key = "";
            let val = "";
            key = i + "[" + j + "]" + "." + k;
            val = params[i][j][k];
            fd.append(key, val);
          }
        }
      }
    } else {
      fd.append(i, params[i]);
    }
  }
  return fd;
};

/**
 * @description: handlePostFormURLENCODED
 * @param {Object} params
 */
const handlePostFormURLENCODED = (params) => {
  let str = "";
  for (let i in params) {
    if (Object.property.hasOwnProperty.call(params, i)) {
      str = str + i + "=" + params[i];
      str += "&";
    }
  }
  str = str.slice(0, str.length - 1);
  return str;
};

/**
 * @description: handlePutFormData
 * @param {Object} params
 */
const handlePutFormData = (params, option) => {
  let headers = { "Content-Type": "application/json;charset=UTF-8" };
  if (option.method === "PUT_FORDATA") {
    let formData = new FormData();
    Object.keys(params).forEach((key) => {
      formData.append(key, params[key]);
    });
    headers = { "Content-Type": "application/x-www-form-urlencoded" };
    params = formData;
  }
  return { headers, params };
};

const $globalRequest = (url = "", params = {}, option = {}) => {
  try {
    const { method } = option;
    const methodStr =
      typeof method === "string" ? method.toUpperCase() : method;
    option.method = methodStr;
    let config = extend({ method: "JSONP" }, option);
    let reqData = {};

    if (["POST_FORMDATA"].includes(methodStr)) {
      const fd = handlePostFormdata(params);
      reqData = {
        url: url,
        headers: {
          "Content-Type": "multipart/form-data",
        },
        data: fd,
      };
      config = extend(config, reqData);
      return post(config).then((res) => {
        return res;
      });
    } else if (["POST_FORM_URLENCODED"].includes(methodStr)) {
      const str = handlePostFormURLENCODED(params);
      reqData = {
        url: url,
        headers: {
          "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
        },
        data: str,
      };
      config = extend(config, reqData);
      return post(config).then((res) => {
        return res;
      });
    } else if (["POST", "POST_JSON"].includes(methodStr)) {
      if (methodStr === "POST_JSON") {
        params = JSON.stringify(params);
      }
      reqData = {
        url: url,
        headers: {
          "Content-Type": "application/json;charset=UTF-8",
        },
        data: params,
      };
      config = extend(config, reqData);
      return post(config).then((res) => {
        return res;
      });
    } else if (["PUT", "PUT_FORDATA"].includes(methodStr)) {
      const { headers, params } = handlePutFormData(params, option);
      reqData = {
        url: url,
        headers: headers,
        data: params,
      };
      config = extend(config, reqData);
      return put(config).then((res) => {
        return res;
      });
    } else if (["DELETE"].includes(methodStr)) {
      reqData = {
        url: url,
        headers: {
          "Content-Type": "application/json",
        },
        params: params,
      };
      config = extend(config, reqData);
      return Delete(config).then((res) => {
        return res;
      });
    } else if (["GET"].includes(methodStr)) {
      reqData = {
        url: url,
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
        params: params,
      };
      config = extend(config, reqData);
      return get(config).then((res) => {
        return res;
      });
    } else if (["JSONP"].includes(methodStr)) {
      return getJsonpData(url, params, null).then((res) => {
        return res;
      });
    } else {
      console.error("请求方式有误，请检查您的请求方式");
      return;
    }
  } catch (error) {
    console.error("请求方式代码异常", error);
  }
};

const $globalRequest1 = axios.create({
  baseURL: '', // 默认的 base URL
  timeout: 5000, // 请求超时时间
});

// 请求拦截器
$globalRequest1.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么，例如添加 token 到 header
    const token = localStorage.getItem('access_token');
    if (token) {
      config.headers['Authorization'] = `bearer ${token}`;
      config.headers['auth_header'] = `Basic cm9vdDpyb290`;
    }
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 响应拦截器
$globalRequest1.interceptors.response.use(
  (response) => {
    console.log("🚀 ~ response:", response)
    // const navigate = useNavigate();
    // 对响应数据做点什么
    if (response.data.code !== 200) {
      switch (response.data.code) {
        case 401001:
          window.location.href = "/login";
          break;
        case 400:
          Toast.error('错误请求');
          break;
        case 401:
          Toast.error('未授权，请登录')
          break;
        case 403:
          Toast.error('禁止访问');
          break;
        case 404:
          Toast.error('请求错误,未找到该资源');
          break;
        case 405:
          Toast.show({
            icon: 'fail',
            content: `${response.data.message}`,
          })
          break;
        case 500:
          Toast.error('服务器端错误');
          break;
        default:
          Toast.error('未知错误');
      }
      Toast.show({
        icon: 'fail',
        content: `${response.data.message}`,
      })
      return Promise.reject(response.data)
    }
    return response.data.data;
  },
  (error) => {
    // 对响应错误做点什么
    const { response } = error;
    if (response && response.status) {
      switch (response.status) {
        case 400:
          Toast.error('错误请求');
          break;
        case 401:
          Toast.error('未授权，请登录')
          break;
        case 403:
          Toast.error('禁止访问');
          break;
        case 404:
          Toast.error('请求错误,未找到该资源');
          break;
        case 405:
          Toast.show({
            icon: 'fail',
            content: `${response.data.message}`,
          })
          break;
        case 500:
          Toast.error('服务器端错误');
          break;
        default:
          Toast.error('未知错误');
      }
    }
    return Promise.reject(error);
  }
);
// const $globalRequest = service;
export { $globalRequestUrl, $globalRequest, $globalUploaderRequest };
